using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Security.DataLayer;
using Security.Domain;
using Security.Helpers;
using Security.Specs.Common;
using Security.Specs.DataLayer;
using Security.Specs.Services;
using Security.Specs.Implementation.Common;

namespace Security.Specs.Implementation.Services
{
    [Export(typeof(IPermissionService))]
    internal class PermissionService : IPermissionService
    {
        private readonly ISecurityDataModel model;
        private ValidationService<Permission> validationService;

        [ImportingConstructor]
        public PermissionService(ISecurityDataModel model)
        {
            this.model = model;
            InitializeValidationService();
        }

        public Permission New()
        {
            return new Permission();
        }

        public ErrorCollection Validate(Permission permission)
        {
            return validationService.GetErrors(permission);
        }

        private void InitializeValidationService()
        {
            validationService = new ValidationService<Permission>();
            validationService.AddRule(p => p.ID.IsEmpty(), StandardErrorReports.IdPropertyNotSet);
            validationService.AddRule(p => string.IsNullOrWhiteSpace(p.Name), StandardErrorReports.NamePropertyNotSet);
            validationService.AddRule(p => model.Permissions.Any(perm => perm.ID != p.ID && perm.Name == p.Name), DuplicatePermission);
        }

        private ErrorReport DuplicatePermission(Permission permission)
        {
            return ErrorReport.Create().
                    InObject(permission).
                    InvalidPropertyName(Property.Name<Permission>(p => p.Name)).
                    Severity(ErrorSeverity.Error).
                    WithMessage(Strings.PermissionWithSameNameAlreadyExists(permission));
        }
    }
}